package net.wexoo.onlinedivelog.dal;

import static org.apache.log4j.Logger.getLogger;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
import org.springframework.transaction.annotation.Transactional;

@Transactional
public abstract class AbstractDAO<T> implements IDAO<T> {

  protected Class<T> clazz;

  @PersistenceContext
  protected EntityManager em;

  @Override
  public T saveOrUpdate(T entity) {
    try {
      em.persist(entity);
    } catch (Exception e) {
      e.printStackTrace();
      getLogger(getClass()).error("Error when saving entity!\n" + e);
    }
    return entity;
  }

  @Override
  public boolean delete(T entity) {
    try {
      em.remove(entity);
    } catch (Exception e) {
      getLogger(getClass()).error("Error when removing entity!\n" + e.toString());
      return false;
    }
    return true;
  }

  @Override
  public List<T> getAll() {
    @SuppressWarnings("unchecked")
    List<T> diveLevelList = em.createQuery("from " + getBeanClassName()).getResultList();

    return new ArrayList<T>(diveLevelList);
  }

  @SuppressWarnings("unchecked")
  @Override
  public List<T> getAll(SortParam sortParam, Integer first, Integer count) {
    StringBuilder queryBuilder = new StringBuilder("from ");
    queryBuilder.append(getBeanClassName());

    if (sortParam != null) {
      queryBuilder.append(" order by ");
      queryBuilder.append(sortParam.getProperty());
      queryBuilder.append(sortParam.isAscending() ? " asc" : " desc");
    }

    Query q = em.createQuery(queryBuilder.toString());

    if (first != null)
      q.setFirstResult(first);
    if (count != null)
      q.setMaxResults(count);

    return q.getResultList();
  }

  @SuppressWarnings("unchecked")
  @Override
  public T getBeanById(int id) {
    return (T) em.createQuery("from " + getBeanClassName() + " where id = " + id).getSingleResult();
  }

  @Override
  public void setClazz(Class<T> clazzToSet) {
    this.clazz = clazzToSet;
  }

  @Override
  public String getBeanClassName() {
    return clazz.getSimpleName();
  }

  @Override
  public Long getCount() {
    return (Long) em.createQuery("select count(*) from " + getBeanClassName()).getSingleResult();
  }
}